<?php
/**
 * Created by PhpStorm.
 * User: lhl
 * Date: 2019/6/4
 * Time: 10:09
 * Features: 加解密相关方法封装
 */

namespace app\common\service;


use think\facade\Config;

class Encrypt
{
    /**
     * 加密
     * @param string $data 原字符串
     * @param string $key 盐值
     * @return string 加密后base64
     */
    public static function encrypt($data, $key){
        $key = md5($key);
        $x = 0;
        $len = strlen($data);
        $l = strlen($key);
        $char = '';
        for ($i = 0;$i < $len;$i++) {
            if ($x == $l) {
                $x = 0;
            }
            $char .= $key{$x};
            $x++;
        }
        $str = '';
        for ($i = 0; $i < $len; $i++) {
            $str .= chr(ord($data{$i}) + (ord($char{$i})) % 256);
        }
        return base64_encode($str);
    }

    /**
     * 解密
     * @param string $data 加密后字符串
     * @param string $key 盐值
     * @return string 解密后字符串
     */
    public static function decrypt($data, $key){
        $key = md5($key);
        $x = 0;
        $data = base64_decode($data);
        $len = strlen($data);
        $l = strlen($key);
        $char = '';
        for ($i = 0;$i < $len;$i++) {
            if ($x == $l) {
                $x = 0;
            }
            $char .= substr($key, $x, 1);
            $x++;
        }
        $str = '';
        for ($i = 0;$i < $len;$i++){
            if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
                $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
            } else {
                $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
            }
        }
        return $str;
    }

    /**
     * 生成盐值
     */
    public static function salt(){
        return StringHelper::getRandString(32);
    }

    /**
     * 用户密码加密
     * @param string $username 账号
     * @param string $password 原密码
     * @param string $salt 加密盐值
     */
    public static function password($username,$password,$salt){
        return md5(self::encrypt($password,$salt).$username);
    }

    /**
     * session数据签名
     * @param array $data 原数据
     *
     * @return array
     * ['sign' => 数据签名]
     */
    public static function sessionSign($data){
        if(isset($data['sign'])){
            unset($data['sign']);
        }
        ksort($data);
        $queryString = base64_encode(strtoupper(http_build_query($data)));
        $queryString .= sha1($queryString.Config::get('session.salt'));
        $data['sign'] = $queryString;
        return $data;
    }

    /**
     * 将数据加密成可逆的token
     * @param  array  $data 原数据
     *
     * @return string 包含原数据和数据签名的token
    */
    public static function sessionTokenEncrypt($data){
        //生成数据签名
        $data = self::sessionSign($data);
        //将数据加密成可逆token的形式
        return self::encrypt(json_encode($data),Config::get('session.salt'));
    }

    /**
     * 将token解密成原数据
     * @param string $token 生成的数据token
     *
     * @return array|bool
    */
    public static function sessionTokenDecrypt($token){
        //将token解密成原数据和token
        $data = json_decode(self::decrypt($token,Config::get('session.salt')),true);
        //根据验证签名 如果签名不对说明数据被篡改 直接返回false
        if(!isset($data['sign']) || $data['sign'] != self::sessionSign($data)['sign']){
            return false;
        }
        unset($data['sign']);
        return $data;
    }
}